package com.openbravo.pos.forms;

import java.awt.CardLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;

import com.openbravo.pos.base.AppLocal;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.JXTaskPaneContainer;

import cn.ekuma.epos.swing.calc.CalcJDialog;
import cn.ekuma.security.I_SecurityManager;


import com.openbravo.beans.RoundedBorder;
import com.openbravo.data.gui.JMessageDialog;
import com.openbravo.data.gui.MessageInf;


import com.openbravo.pos.base.AppUserView;
import com.openbravo.pos.base.I_AppView;
import com.openbravo.bean.I_AppUser;
import com.openbravo.pos.scripting.ScriptEngine;
import com.openbravo.pos.scripting.ScriptException;
import com.openbravo.pos.scripting.ScriptFactory;

public abstract class AbstratJPrincipalApp<T extends I_AppUser>  extends javax.swing.JPanel implements AppUserView<T> {

    private static Logger logger = Logger.getLogger("com.openbravo.pos.forms.AbstratJPrincipalApp");
   
    protected T appuser;
    
    private JLabel m_principalnotificator;
    
    protected JPanelView m_jLastView;    
    protected Action m_actionfirst;
    
    protected Map<String, JPanelView> m_aPreparedViews; // Prepared views   
    protected Map<String, JPanelView> m_aCreatedViews;
    
    private Icon menu_open;
    private Icon menu_close;
    private JPopupMenu    mainMenu;


	private I_SecurityManager security;

	private I_AppView m_appview;

	
    /** Creates new form JPrincipalApp */
    public AbstratJPrincipalApp(I_AppView appview,T appuser) {
    	m_appview=appview;
        this.appuser = appuser;
                       
        m_actionfirst = null;
        m_jLastView = null;
        m_aPreparedViews = new HashMap<String, JPanelView>();
        m_aCreatedViews = new HashMap<String, JPanelView>();
        mainMenu=new javax.swing.JPopupMenu(AppLocal.getIntString("mainMenu.name"));
        initComponents();

        KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
        ActionListener actionListener = new ActionListener() {
           @Override
              public void actionPerformed(ActionEvent actionEvent) {
                 escapeKeyProc();
          }
        };
        registerKeyboardAction(actionListener, stroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

        stroke = KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0);
        actionListener = new ActionListener() {
           @Override
              public void actionPerformed(ActionEvent actionEvent) {
                 downHomeProc();
          }
        };
        registerKeyboardAction(actionListener, stroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

         stroke = KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,InputEvent.ALT_DOWN_MASK);
         actionListener = new ActionListener() {
           @Override
              public void actionPerformed(ActionEvent actionEvent) {
        	   if(!isAdminLogin())
        		   return;
        	   String inputValue = JOptionPane.showInputDialog("Please input a value");
        	   if(inputValue!=null&&!inputValue.isEmpty())
        		   showTaskAdmin(inputValue);
          }
        };
        registerKeyboardAction(actionListener, stroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        
        jPanel2.add(Box.createVerticalStrut(50), 0);        
        
        applyComponentOrientation(appview.getComponentOrientation());
        
        m_principalnotificator = new JLabel();
        m_principalnotificator.applyComponentOrientation(getComponentOrientation());
        m_principalnotificator.setText(appuser.getName());
       // m_principalnotificator.setIcon(m_appuser.getIcon());
//        m_principalnotificator.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createLineBorder(javax.swing.UIManager.getDefaults().getColor("TextField.shadow")), javax.swing.BorderFactory.createEmptyBorder(1, 5, 1, 5)));        
        
        if (jButton1.getComponentOrientation().isLeftToRight()) {
            menu_open = new javax.swing.ImageIcon(getClass().getResource("/com/openbravo/images/menu-right.png"));
            menu_close = new javax.swing.ImageIcon(getClass().getResource("/com/openbravo/images/menu-left.png"));
        } else {
            menu_open = new javax.swing.ImageIcon(getClass().getResource("/com/openbravo/images/menu-left.png"));
            menu_close = new javax.swing.ImageIcon(getClass().getResource("/com/openbravo/images/menu-right.png"));
        }
        assignMenuButtonIcon();        
                
        // m_jPanelTitle.setUI(new GradientUI());
        m_jPanelTitle.setBorder(RoundedBorder.createGradientBorder());
        m_jPanelTitle.setVisible(false);
        
        // Anado el panel nulo
        m_jPanelContainer.add(new JPanel(), "<NULL>");
        showView("<NULL>");     
        
      /** try {
           String menuModel=System.getProperty(AppLocal.APP_MenuModelPropName, AppLocal.APP_DefaultMenuModel);
           String menuText=null;
           if(!AppLocal.APP_MenuModel_POS.equalsIgnoreCase(menuModel)){
                RoleUtil.fillOrderTypePermission(appuser, m_dlSystem);
                RoleUtil.fillUserStateProcessPermission(appuser, m_dlSystem);
                menuText=m_dlSystem.getResourceAsText(menuModel+"."+appuser.getName());
           }
           if(menuText==null||menuText.isEmpty())
               menuText=m_dlSystem.getResourceAsText(menuModel);
           m_jPanelLeft.setViewportView(getScriptMenu(menuText));
        } catch (ScriptException e) {
            logger.log(Level.SEVERE, "Cannot read Menu.Root resource. Trying defaut menu.", e);
            try {
                m_jPanelLeft.setViewportView(getScriptMenu(StringUtils.readResource("/com/openbravo/pos/templates/Menu.Root.txt")));
            } catch (IOException ex) {
                logger.log(Level.SEVERE, "Cannot read default menu", ex);
            } catch (ScriptException es) {
                logger.log(Level.SEVERE, "Cannot read default menu", es);
            }
        }*/
    }

      private void downHomeProc() {
             CalcJDialog.showCalcJDialog(this, true);
      };

       private void escapeKeyProc() {
           if(mainMenu.isShowing())
               mainMenu.setVisible(false);
           else{
               int x=(getWidth()-mainMenu.getWidth())/2;
               int y=(getHeight()-mainMenu.getHeight())/2;
               mainMenu.show(this,x,y);
           }
       }

    protected Component getScriptMenu(String menutext) throws ScriptException {
        ScriptMenu menu = new ScriptMenu();
        ScriptEngine eng = ScriptFactory.getScriptEngine(ScriptFactory.BEANSHELL);
        eng.put("menu", menu);
        eng.eval(menutext);
        return menu.getTaskPane();
    }
    
    private void assignMenuButtonIcon() {
        jButton1.setIcon(m_jPanelLeft.isVisible()
                ? menu_close
                : menu_open);
    }
    
    public class ScriptMenu {
//        private JTaskPane taskPane = new JTaskPane();
        private JXTaskPaneContainer taskPane;
        
        private ScriptMenu() {
            taskPane = new JXTaskPaneContainer();
            taskPane.applyComponentOrientation(getComponentOrientation());
        }
        
        public ScriptGroup addGroup(String key) {
            
            ScriptGroup group = new ScriptGroup(key);
            taskPane.add(group.getTaskGroup());
            return group;
        }
        
//        public JTaskPane getTaskPane() {            
        public JXTaskPaneContainer getTaskPane() {            
            return taskPane;
        }
    }
    
    public class ScriptGroup {
//        private JTaskPaneGroup taskGroup;
        private JXTaskPane taskGroup;
        
        private ScriptGroup(String key) {
//            taskGroup = new JTaskPaneGroup();
            taskGroup = new JXTaskPane();
            taskGroup.applyComponentOrientation(getComponentOrientation());
            taskGroup.setFocusable(false);
            taskGroup.setRequestFocusEnabled(false);
            taskGroup.setTitle(AppLocal.getIntString(key));
            taskGroup.setVisible(false); // Only groups with sons are visible.
            mainMenu.addSeparator();
        }
        
        public void addPanel(String icon, String key, String classname) {            
            addAction(new MenuPanelAction(m_appview, icon, key, classname));
        }        
        public void addExecution(String icon, String key, String classname) {
            addAction(new MenuExecAction(m_appview, icon, key, classname));
        }        
        public ScriptSubmenu addSubmenu(String icon, String key, String classname) {
            ScriptSubmenu submenu = new ScriptSubmenu(key); 
            m_aPreparedViews.put(classname, new JPanelMenu(submenu.getMenuDefinition()));
            addAction(new MenuPanelAction(m_appview, icon, key, classname));
            return submenu;
        }        
        public void addChangePasswordAction() {            
            addAction(new ChangePasswordAction("/com/openbravo/images/yast_security.png", "Menu.ChangePassword"));
        }       
        public void addExitAction() {            
            addAction(new ExitAction("/com/openbravo/images/gohome.png", "Menu.Exit"));
        }
        
        public void addLockScreenAction() {
        	addAction(new LockScreenAction("/com/openbravo/images/yast_security.png", "Menu.LockScreen"));
        }
        
        private void addAction(Action act) { 
           // if (security.hasPermissionByName((String) act.getValue(AppUserView.ACTION_TASKNAME))) {
                // add the action
                Component c = taskGroup.add(act);
                c.applyComponentOrientation(getComponentOrientation());
                c.setFocusable(false);
                //c.setRequestFocusEnabled(false);   
                mainMenu.add(act);
                taskGroup.setVisible(true);

                if (m_actionfirst == null) {
                    m_actionfirst = act;
                }
            //}
        }
        
//        public JTaskPaneGroup getTaskGroup() {
        public JXTaskPane getTaskGroup() {
            return taskGroup;
        }   
    }
    
    public class ScriptSubmenu {
        private MenuDefinition menudef;
        
        private ScriptSubmenu(String key) {
            menudef = new MenuDefinition(key);
        }
        
        public void addTitle(String key) {
            menudef.addMenuTitle(key);
        }
        
        public void addPanel(String icon, String key, String classname) {
            menudef.addMenuItem(new MenuPanelAction(m_appview, icon, key, classname));
        }
        public void addExecution(String icon, String key, String classname) {
            menudef.addMenuItem(new MenuExecAction(m_appview, icon, key, classname));
        }                
        public ScriptSubmenu addSubmenu(String icon, String key, String classname) {
            ScriptSubmenu submenu = new ScriptSubmenu(key); 
            m_aPreparedViews.put(classname, new JPanelMenu(submenu.getMenuDefinition()));
            menudef.addMenuItem(new MenuPanelAction(m_appview, icon, key, classname));
            return submenu;
        } 
        public void addChangePasswordAction() {            
            menudef.addMenuItem(new ChangePasswordAction("/com/openbravo/images/yast_security.png", "Menu.ChangePassword"));
        }        
        public void addExitAction() {
            menudef.addMenuItem(new ExitAction("/com/openbravo/images/gohome.png", "Menu.Exit"));
        }
        
        public void addLockScreenAction() {
            menudef.addMenuItem(new LockScreenAction("/com/openbravo/images/yast_security.png", "Menu.LockScreen"));
        }
        
        public MenuDefinition getMenuDefinition() {
            return menudef;
        }
    }
    
    protected void setMenuVisible(boolean value) {
        m_jPanelLeft.setVisible(value);
        assignMenuButtonIcon();
        m_appview.setMaxWindow(!value);
        revalidate();
    }
        
    public JComponent getNotificator() {
        return m_principalnotificator;
    }
    
    public abstract void activate();
    
    public boolean deactivate() {
        if (m_jLastView == null) {
            return true;
        } else if (m_jLastView.deactivate()) {
            m_jLastView = null;
            showView("<NULL>");       
            return true;
        } else {
            return false;
        }
        
    }
    
    private class ExitAction extends AbstractAction {
        
        public ExitAction(String icon, String keytext) {
            putValue(Action.SMALL_ICON, new ImageIcon(AbstratJPrincipalApp.class.getResource(icon)));
            putValue(Action.NAME, AppLocal.getIntString(keytext));
            putValue(AppUserView.ACTION_TASKNAME, keytext);
        }
        public void actionPerformed(ActionEvent evt) {
            m_appview.closeAppView();
        }
    }
    
    
    // La accion de cambio de password..
    private class ChangePasswordAction extends AbstractAction {
        public ChangePasswordAction(String icon, String keytext) {
            putValue(Action.SMALL_ICON, new ImageIcon(AbstratJPrincipalApp.class.getResource(icon)));
            putValue(Action.NAME, AppLocal.getIntString(keytext));
            putValue(AppUserView.ACTION_TASKNAME, keytext);

        }
        public void actionPerformed(ActionEvent evt) {
        	changePassword();
        }
    }
    
    public abstract void changePassword();
    
    
    private class LockScreenAction extends AbstractAction {
        public LockScreenAction(String icon, String keytext) {
            putValue(Action.SMALL_ICON, new ImageIcon(AbstratJPrincipalApp.class.getResource(icon)));
            putValue(Action.NAME, AppLocal.getIntString(keytext));
            putValue(AppUserView.ACTION_TASKNAME, keytext);

        }
        public void actionPerformed(ActionEvent evt) {
        	lockScreen();
        }
    }
    
    public abstract void  lockScreen();
    
    private void showView(String sView) {
        CardLayout cl = (CardLayout)(m_jPanelContainer.getLayout());
        cl.show(m_jPanelContainer, sView);       
    }
    
    public T getUser() {
        return appuser;
    }
    
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        m_jPanelLeft = new javax.swing.JScrollPane();
        m_jPanelRight = new javax.swing.JPanel();
        m_jPanelTitle = new javax.swing.JPanel();
        m_jTitle = new javax.swing.JLabel();
        m_jPanelContainer = new javax.swing.JPanel();

        setLayout(new java.awt.BorderLayout());

        jPanel1.setLayout(new java.awt.BorderLayout());

        jPanel2.setLayout(new javax.swing.BoxLayout(jPanel2, javax.swing.BoxLayout.Y_AXIS));

        jButton1.setFocusPainted(false);
        jButton1.setFocusable(false);
        jButton1.setMargin(new java.awt.Insets(14, 2, 14, 2));
        jButton1.setRequestFocusEnabled(false);
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        jPanel2.add(jButton1);

        jPanel1.add(jPanel2, java.awt.BorderLayout.LINE_END);
        jPanel1.add(m_jPanelLeft, java.awt.BorderLayout.CENTER);

        add(jPanel1, java.awt.BorderLayout.LINE_START);

        m_jPanelRight.setLayout(new java.awt.BorderLayout());

        m_jPanelTitle.setLayout(new java.awt.BorderLayout());

        m_jTitle.setFont(new java.awt.Font("SansSerif", 1, 18)); // NOI18N
        m_jTitle.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 1, 0, java.awt.Color.darkGray), javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)));
        m_jPanelTitle.add(m_jTitle, java.awt.BorderLayout.NORTH);

        m_jPanelRight.add(m_jPanelTitle, java.awt.BorderLayout.NORTH);

        m_jPanelContainer.setLayout(new java.awt.CardLayout());
        m_jPanelRight.add(m_jPanelContainer, java.awt.BorderLayout.CENTER);

        add(m_jPanelRight, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed

    setMenuVisible(!m_jPanelLeft.isVisible());
    
}//GEN-LAST:event_jButton1ActionPerformed

	// Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    protected javax.swing.JPanel m_jPanelContainer;
    protected javax.swing.JScrollPane m_jPanelLeft;
    private javax.swing.JPanel m_jPanelRight;
    protected javax.swing.JPanel m_jPanelTitle;
    protected javax.swing.JLabel m_jTitle;
    // End of variables declaration//GEN-END:variables

    
    
    
    public void showTask(String sTaskClass) {

        if (security.hasPermissionByName(sTaskClass)) {
        	showTaskAdmin(sTaskClass);
        } else  {
            // No hay permisos para ejecutar la accion...
            JMessageDialog.showMessage(this, new MessageInf(MessageInf.SGN_WARNING, AppLocal.getIntString("message.notpermissions")));
        }
       
    }

    public abstract void showTaskAdmin(String sTaskClass);
    
    public abstract void executeTask(String sTaskClass);
    
    public abstract boolean isAdminLogin();
}
